package com.jztchat.webSocket;

import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import com.jztchat.asyncTask.chatRecordTask.RecordChatHandler;
import com.jztchat.redis.RedisKeyConstent;
import com.jztchat.redis.RedisListenHandler;
import com.jztchat.repository.ChatRecordRepository;
import com.jztchat.repository.ClientInfoRepository;
import com.jztchat.entity.ChatRecord;
import com.jztchat.entity.ClientInfo;
import com.jztchat.util.JsonUtil;
import com.jztchat.webSocket.service.SocketConnectService;
import com.jztchat.dataobject.MessageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * Created by zzy on 2018/1/18.
 */
@Component
public class SocketHandler {

    private final static Logger logger= LoggerFactory.getLogger(SocketHandler.class);

    private final ConcurrentMap<String, RedisListenHandler> redisListenerMap = new ConcurrentHashMap<>();



    private final SocketIOServer server;

    private final RedisMessageListenerContainer redisMessageListenerContainer;


    @Autowired
    public SocketHandler(SocketIOServer server, RedisMessageListenerContainer redisMessageListenerContainer)
    {
        this.server = server;
        this.redisMessageListenerContainer = redisMessageListenerContainer;
    }
    @Autowired
    private ClientInfoRepository clientInfoRepository;
    @Autowired
    private SocketConnectService socketConnectService;
    @Autowired
    private ChatRecordRepository chatRecordRepository;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //添加connect事件，当客户端发起连接时调用，本文中将clientid与sessionid存入数据库
    //方便后面发送消息时查找到对应的目标client, (以后可用redis代替)
    @OnConnect
    public void onConnect(SocketIOClient client){
          //记录链接
         String clientId=client.getHandshakeData().getSingleUrlParam("clientId");
         ClientInfo clientInfo=clientInfoRepository.findByClientid(clientId);
         if(clientInfo!=null){
             Date nowTime = new Date(System.currentTimeMillis());
             clientInfo.setConnected((short)1);
             clientInfo.setMostsignbits(client.getSessionId().getMostSignificantBits());
             clientInfo.setLeastsignbits(client.getSessionId().getLeastSignificantBits());
             clientInfo.setLastconnecteddate(nowTime);
             clientInfoRepository.save(clientInfo);
             socketConnectService.saveClientInfoToRedis(clientInfo);
         }
         //查看是否有未接收的消息
        ChatRecord chatRecord=socketConnectService.getChatRecordFormRids(clientId);
         if(chatRecord==null){
             List<ChatRecord> chatRecordList=chatRecordRepository.findByTargetUserAndIsSend(clientId,2);
             chatRecord= CollectionUtils.isEmpty(chatRecordList)?null:chatRecordList.get(0);
         }
         if(chatRecord!=null) {
             redisListenerMap.put(client.getSessionId().toString(), new RedisListenHandler(server));

             RedisListenHandler redisListener = redisListenerMap.get(client.getSessionId().toString());
             redisMessageListenerContainer
                     .addMessageListener(redisListener, new ChannelTopic("chatRecord:" + clientId));
             stringRedisTemplate.convertAndSend("chatRecord:" + clientId, JsonUtil.Object2Json(chatRecord));
         }
        //server.getClient(uuid).sendEvent("messageevent", sendData);

    }

    //添加@OnDisconnect事件，客户端断开连接时调用，刷新客户端信息
    @OnDisconnect
    public void onDisconnect(SocketIOClient client)
    {
        String clientId=client.getHandshakeData().getSingleUrlParam("clientId");
        ClientInfo clientInfo = clientInfoRepository.findByClientid(clientId);
        if (clientInfo != null)
        {
            clientInfo.setConnected((short)0);
            clientInfo.setMostsignbits(null);
            clientInfo.setLeastsignbits(null);
            clientInfoRepository.save(clientInfo);
        }
        RedisListenHandler redisListener = redisListenerMap.get(client.getSessionId().toString());
        redisMessageListenerContainer.removeMessageListener(redisListener);
    }

    //消息接收入口，当接收到消息后，查找发送目标客户端，并且向该客户端发送消息，且给自己发送消息
    @OnEvent(value = "messageevent")
    public void onEvent(SocketIOClient client, AckRequest request, MessageInfo data)
    {
        String targetClientId = data.getTargetClientId();
        String clientId = client.getHandshakeData().getSingleUrlParam("clientId");
        //先从redis中取
        ClientInfo clientInfo;
        Integer isSend=2;
        String key= RedisKeyConstent.CHAT_USER_LOGIN_INFO+targetClientId;
        clientInfo=socketConnectService.getClientInfoToRedis(key);
        if(clientInfo==null){
            clientInfo = clientInfoRepository.findByClientid(targetClientId);
        }
        MessageInfo sendData = new MessageInfo();
        sendData.setSourceClientId(data.getSourceClientId());
        sendData.setTargetClientId(data.getTargetClientId());
        sendData.setMsgType("chat");
        sendData.setMsgContent(data.getMsgContent());
        client.sendEvent("messageevent", sendData);
        if (clientInfo != null && clientInfo.getConnected() != 0)
        {
            UUID uuid = new UUID(clientInfo.getMostsignbits(), clientInfo.getLeastsignbits());
            System.out.println(uuid.toString());
            server.getClient(uuid).sendEvent("messageevent", sendData);
            isSend=1;
        }
        //通知存储聊天记录
        ChatRecord chatRecord=ChatRecord.getChatRecord(sendData,data.getSourceClientId(),targetClientId,isSend);
        RecordChatHandler.queue.add(chatRecord);
    }
}
